/*
  Author: Chen Haodong (shinkunyachen@outlook.com)
  -----
  Copyright (c)2021 - present Chen Haodong. All Rights Reserved.
 */

#ifndef BRANCH_CHECKER_H
#define BRANCH_CHECKER_H

#include "BranchAnalyzer.h"
#include "LCFG.h"
#include "framework/BasicChecker.h"
#include "framework/Report.h"
#include <clang/AST/ASTConsumer.h>
#include <clang/AST/RecursiveASTVisitor.h>
#include <sstream>
#include <string>
#include <unordered_map>
#include <vector>
struct BranchCheckerOptions
{
    bool enable_code_layout = false;
    bool enable_likely_unlikely = false;
    size_t code_count_threshold = 5;
    double likely_threshold = 0.85;
    double unlikely_threshold = 0.15;
};
class BranchChecker : public BasicChecker
{
public:
    BranchChecker(ASTResource *resource, ASTManager *manager,
                  CallGraph *call_graph, Config *configure);
    void check();

    const BranchCheckerOptions &options() const {return _options;}
    const BranchAnalyzer &analyzer() const { return _analyzer; }

private:
    BranchCheckerOptions _options;
    BranchAnalyzer _analyzer;
};
class BranchCheckerVisitor : public clang::RecursiveASTVisitor<BranchCheckerVisitor>
{
public:
    BranchCheckerVisitor(
        BranchChecker &checker,clang::ASTContext &ctx)
        : _checker(checker),_ast_ctx(ctx) {}
    bool VisitStmt(clang::Stmt *stmt);

    void generate_report(ReportSpace::DefectName dn, ReportSpace::DefectType dt,const clang::Stmt *stmt,const std::string &desc);
private:
    BranchChecker &_checker;
    clang::ASTContext &_ast_ctx;
};
class BranchCheckerConsumer : public clang::ASTConsumer
{
public:
    BranchCheckerConsumer(
        BranchChecker &checker,clang::ASTContext &ctx)
        : visitor(checker,ctx) {}
    virtual void HandleTranslationUnit(clang::ASTContext &ctx)
    {
        visitor.TraverseDecl(ctx.getTranslationUnitDecl());
    }

private:
    BranchCheckerVisitor visitor;
};
#endif